/**
 *
 */
package de.cbf.cam.dsa.model.entities;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import de.cbf.cam.dsa.model.entities.maneuvers.ManeuverDesc;
import de.cbf.cam.dsa.model.persistence.Header;
import de.cbf.util.modifier.entities.OneModifier;

/**
 * @author Nebelritter
 *
 */
@Entity
public class OneAction extends Header implements Comparable<OneAction> {

	/**
	 * @uml.property  name="actor"
	 * @uml.associationEnd  multiplicity="(1 1)" inverse="actions:de.cbf.cam.dsa.model.entities.BattleChar"
	 */
	protected BattleChar actor;
	/**
	 * @uml.property  name="ini"
	 */
	protected int ini;
	/**
	 * @uml.property  name="realized"
	 */
	protected boolean realized = false; //was acted
	/**
	 * @uml.property  name="type"
	 */
	protected int type;

	/**
	 * @uml.property  name="text"
	 */
	protected String text="";
	/**
	 * @uml.property  name="possibleManeuvers"
	 * @uml.associationEnd  multiplicity="(0 -1)" elementType="de.cbf.cam.dsa.model.entities.maneuvers.ManeuverDesc"
	 */
	protected List<ManeuverDesc> possibleManeuvers = new ArrayList<ManeuverDesc>();
	/**
	 * @uml.property  name="actionModifiers"
	 * @uml.associationEnd  multiplicity="(0 -1)" elementType="de.cbf.cam.dsa.model.entities.OneModifier"
	 */
	protected List<OneModifier> actionModifiers = new ArrayList<OneModifier>();

	public static String PROPERTYNAME= "OneAction:";
	/**
	 * @uml.property  name="propertyChangeSupport"
	 */
	public PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
	/**
	 * @uml.property  name="propertyChangeAdvance"
	 * @uml.associationEnd  multiplicity="(1 1)" inverse="this$0:de.cbf.cam.dsa.model.entities.OneAction$PropertyChangeAdvanceListener"
	 */
	private PropertyChangeAdvanceListener propertyChangeAdvance = new PropertyChangeAdvanceListener();
	/**
	 *
	 */
	public OneAction(BattleChar actor) {
		this.actor=actor;
		actor.propertyChangeSupport.addPropertyChangeListener(propertyChangeAdvance);
	}

	public boolean isSameAs(OneAction action){
		boolean result=true;
		if(action==null) return false;
		result = result&&this.actor==action.actor;
		result = result&&this.ini==action.ini;
		return result;
	}

	public void removeAllActionModifiers(){
		actionModifiers.clear();
	}

	public boolean addActionModifier(OneModifier modifier){
		return actionModifiers.add(modifier);
	}
	public boolean removeActionModifier(OneModifier modifier){
		return actionModifiers.remove(modifier);
	}

	/**
	 * @return
	 * @uml.property  name="actor"
	 */
	@OneToOne(cascade=CascadeType.ALL)
	public BattleChar getActor() {
		return actor;
	}
	/**
	 * @return
	 * @uml.property  name="ini"
	 */
	public int getIni() {
		return ini;
	}
	/**
	 * @return
	 * @uml.property  name="realized"
	 */
	public boolean isRealized() {
		return realized;
	}
	/**
	 * @return
	 * @uml.property  name="type"
	 */
	public int getType() {
		return type;
	}
	@ManyToMany(cascade=CascadeType.ALL)
	public List<ManeuverDesc> getPossibleManeuvers() {
		return possibleManeuvers;
	}
	/**
	 * @return
	 * @uml.property  name="text"
	 */
	public String getText() {
		return text;
	}

	/**
	 * @return the actionModifiers
	 */
	@Transient
	public List<OneModifier> getAllActionModifiers() {
		List<OneModifier> result = new ArrayList<OneModifier>();
		result.addAll(actor.getModifiers());
		result.addAll(actionModifiers);
		return result;
	}

	/**
	 * @param actor
	 * @uml.property  name="actor"
	 */
	public void setActor(BattleChar actor) {
		this.actor = actor;
	}
	/**
	 * @param ini
	 * @uml.property  name="ini"
	 */
	public void setIni(int ini) {
		this.ini = ini;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"ini", null, this);
	}
	/**
	 * @param realized
	 * @uml.property  name="realized"
	 */
	public void setRealized(boolean realized) {
		this.realized = realized;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"realized", null, this);
	}
	/**
	 * @param type
	 * @uml.property  name="type"
	 */
	public void setType(int type) {
		this.type = type;
	}
	public void setPossibleManeuvers(List<ManeuverDesc> possibleManeuvers) {
		this.possibleManeuvers = possibleManeuvers;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"possibleManeuvers", null, this);
	}
	/**
	 * @param text
	 * @uml.property  name="text"
	 */
	public void setText(String text) {
		this.text = text;
		propertyChangeSupport.firePropertyChange(PROPERTYNAME+"text", null, this);
	}

	public int compareTo(OneAction other) {
		if(this.ini<other.ini){
			return -1;
		}
		if(this.ini>other.ini){
			return 1;
		}
		if(this.ini==other.ini){
			return 0;
		}
		return 0;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		if(actor!=null){
			return "Action:"+actor.getCharacter().getName()+":"+ini;
		}
		return super.toString();
	}

	@Override
	@Id
	public String getGuid() {
		return guid;
	}

	@Override
	protected void setGuid(String guid) {
		this.guid = guid;
	}

	/**
	 * @return the actionModifiers
	 */
	@ManyToMany(cascade=CascadeType.ALL)
	protected List<OneModifier> getActionModifiers() {
		return actionModifiers;
	}

	/**
	 * @param actionModifiers the actionModifiers to set
	 */
	protected void setActionModifiers(List<OneModifier> actionModifiers) {
		this.actionModifiers = actionModifiers;
	}
	private class PropertyChangeAdvanceListener implements PropertyChangeListener{
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			propertyChangeSupport.firePropertyChange(PROPERTYNAME+evt.getPropertyName(),null,OneAction.this);
		}
	}
}
